###############################################################################
# Globals #####################################################################
###############################################################################

__version__ = '0.0.2'
__date__ = 'Date: 2007/10/11'
__author__ = 'Bart Robinson <bartrobinson76@yahoo.com>'
__doc__ = ''
__all__ = ["Nurbs"]

###############################################################################
# Imports #####################################################################
###############################################################################

import Numeric
from CG.Geometry.Points import Point3D

###############################################################################
# Classes and Methods #########################################################
###############################################################################

class Nurbs:
    """
    Nurbs()
    Nurbs(orderInteger, knotsList, weightsList, pointsList)

	 e.g. - Nurbs(order = 2, knots = [0,0,0,1,2,3,4,5,5,5], weights = [1,1,1,1,1,1,1], points = [Point([0,1,0]),Point([1,1,0]),Point([2,1,0]),Point([6,5,0]),Point([10,1,0]),Point([11,1,0]),Point([12,1,0])])
    """
    def __init__(self, order = None, knots = [], weights = [], points = []):
        self.order = order
        self.knots = knots
        self.weights = weights
        self.points = points

    def EvaluateCurve(self, tmax, steps):
        curve = []
        for i in range(steps):
            t = i * (tmax * 0.999 / steps)
            c = self.EvaluatePoint(t, self.order, self.points, self.weights, self.knots)
            curve.append(c)
            #c.Print()
        return curve

    def EvaluatePoint(self, t, order, points, weights, knots):
        c = Point3D([0,0,0])
        rational = 0
        i = 0
        while i < len(points):
            b = self.B(i, order, t, knots)
            p = points[i] * (b * weights[i])
            c = c + p
            rational = rational + b*weights[i]
            i = i + 1
        return c * (1.0/rational)

    def B(self,i,k,t,knots):
        ret = 0
        if k>0:
            n1 = (t-knots[i])* self.B(i,k-1,t,knots)
            d1 = knots[i+k] - knots[i]
            n2 = (knots[i+k+1] - t) * self.B(i+1,k-1,t,knots)
            d2 = knots[i+k+1] - knots[i+1]
            if d1 > 0.0001 or d1 < -0.0001:
                a = n1 / d1
            else:
                a = 0
            if d2 > 0.0001 or d2 < -0.0001:
                b = n2 / d2
            else:
                b = 0
            ret = a + b
            #print "B i = %d, k = %d, ret = %g, a = %g, b = %g\n"%(i,k,ret,a,b)
        else:
            if knots[i] <= t and t <= knots[i+1]:
                ret = 1
            else:
                ret = 0
        return ret

"""
order = 2
knots = [0,0,0,1,2,3,4,5,5,5]
weights = [1,1,1,1,1,1,1]
points = [Point([0,1,0]),Point([1,1,0]),Point([2,1,0]),Point([6,5,0]),Point([10,1,0]),Point([11,1,0]),Point([12,1,0])]

cv = Nurbs(order, knots, weights, points)
cv.EvaluateCurve(1, 10)
cv.EvaluatePoint(0.999, cv.order, cv.points, cv.weights, cv.knots).Print()
v = Viewer()
v.createPoints(cv)
v.createNURBS(cv)
v.mainloop()
"""